/*
 * @Author: xiaosihan
 * @Date: 2022-08-20 14:50:15
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-10-30 19:37:33
 */
import { AmbientLight, Color, DirectionalLight, LinearFilter, NoBlending, PointLight, RGBAFormat, ShaderChunk, ShaderMaterial, Vector2, Vector3, WebGLRenderTarget } from 'three';
import ThreeBase from 'three-base';
import SiChuanMap from './SiChuanMap/SiChuanMap';
import { autorun } from 'mobx';
import { fullScreenMesh } from 'three-base/shaders';
import utils from '@utils';
import ChengDuMap from './ChengDuMap/ChengDuMap';
import chengduMap3DStore from './chengduMap3DStore';

// 成都地图渲染器
class ChengduMapRender extends ThreeBase {
  constructor() {
    super();
  }

  // 环境光
  ambientLight = (() => {
    const ambientLight = new AmbientLight('#fff', 0.3);
    this.scene.add(ambientLight);
    return ambientLight;
  })();

  //点光源
  pointLight = (() => {
    const pointLight = new PointLight('#fff', 0.3);
    pointLight.position.set(50, 40, 50);
    this.scene.add(pointLight);
    return pointLight;
  })();

  // 方向光
  directionalLight = (() => {
    const directionalLight = new DirectionalLight('#fff', 0.3);
    directionalLight.position.set(-10, 10, 5);
    directionalLight.target.position.set(0, 0, 0);
    directionalLight.castShadow = true;
    directionalLight.shadow.mapSize.set(1024, 1024);
    this.scene.add(directionalLight);
    return directionalLight;
  })();

  disposer = autorun(() => {
    const { areaCode } = chengduMap3DStore;
    switch (areaCode) {
      // 成都视角
      case 510100:
        this.setLookAt({
          position: new Vector3(-0.143, 2.051, 0.862),
          center: new Vector3(-0.129, -0.055, 0.11),
        });
        break;

      //"name": "锦江区",510104,
      case 510104:
        this.setLookAt({
          position: new Vector3(0.151, 0.293, 0.237),
          center: new Vector3(0.15, -0.055, 0.109),
        });
        break;
      //"name": "青羊区", 510105,
      case 510105:
        this.setLookAt({
          position: new Vector3(0.021, 0.285, 0.155),
          center: new Vector3(0.02, -0.029, 0.039),
        });
        break;
      //"name": "金牛区", 510106,
      case 510106:
        this.setLookAt({
          position: new Vector3(0.073, 0.317, 0.119),
          center: new Vector3(0.074, -0.015, -0.001),
        });
        break;
      //"name": "武侯区", 510107,
      case 510107:
        this.setLookAt({
          position: new Vector3(0.05, 0.31, 0.252),
          center: new Vector3(0.05, -0.058, 0.119),
        });
        break;
      //"name": "成华区", 510108,
      case 510108:
        this.setLookAt({
          position: new Vector3(0.185, 0.318, 0.173),
          center: new Vector3(0.185, -0.032, 0.047),
        });
        break;
      //"name": "龙泉驿区", 510112,
      case 510112:
        this.setLookAt({
          position: new Vector3(0.315, 0.522, 0.338),
          center: new Vector3(0.312, -0.067, 0.139),
        });
        break;
      //"name": "青白江区", 510113,
      case 510113:
        this.setLookAt({
          position: new Vector3(0.329, 0.474, 0.134),
          center: new Vector3(0.33, -0.001, -0.038),
        });
        break;
      //"name": "新都区", 510114,
      case 510114:
        this.setLookAt({
          position: new Vector3(0.126, 0.492, 0.106),
          center: new Vector3(0.132, 0.022, -0.078),
        });
        break;
      //"name": "温江区", 510115,
      case 510115:
        this.setLookAt({
          position: new Vector3(-0.18, 0.498, 0.219),
          center: new Vector3(-0.18, -0.016, -0.002),
        });
        break;
      //"name": "双流区", 510116,
      case 510116:
        this.setLookAt({
          position: new Vector3(-0.016, 0.761, 0.602),
          center: new Vector3(-0.014, -0.118, 0.284),
        });
        break;
      //"name": "郫都区", 510117,
      case 510117:
        this.setLookAt({
          position: new Vector3(-0.107, 0.466, 0.08),
          center: new Vector3(-0.106, 0.015, -0.083),
        });
        break;
      //"name": "金堂县", 510121,
      case 510121:
        this.setLookAt({
          position: new Vector3(0.571, 0.804, 0.351),
          center: new Vector3(0.573, -0.031, 0.048),
        });
        break;
      //"name": "大邑县", 510129,
      case 510129:
        this.setLookAt({
          position: new Vector3(-0.648, 0.823, 0.428),
          center: new Vector3(-0.647, -0.056, 0.11),
        });
        break;
      //"name": "蒲江县", 510131,
      case 510131:
        this.setLookAt({
          position: new Vector3(-0.493, 0.462, 0.701),
          center: new Vector3(-0.492, -0.185, 0.467),
        });
        break;
      //"name": "新津区", 510118,
      case 510118:
        this.setLookAt({
          position: new Vector3(-0.165, 0.438, 0.48),
          center: new Vector3(-0.164, -0.116, 0.279),
        });
        break;
      //"name": "都江堰市", 510181,
      case 510181:
        this.setLookAt({
          position: new Vector3(-0.311, 0.995, 0.1),
          center: new Vector3(-0.309, 0.07, -0.235),
        });
        break;
      //"name": "彭州市", 510182,
      case 510182:
        this.setLookAt({
          position: new Vector3(-0.088, 0.864, -0.074),
          center: new Vector3(-0.086, 0.11, -0.347),
        });
        break;
      //"name": "邛崃市", 510183,
      case 510183:
        this.setLookAt({
          position: new Vector3(-0.625, 0.785, 0.678),
          center: new Vector3(-0.623, -0.14, 0.344),
        });
        break;
      //"name": "崇州市", 510184,
      case 510184:
        this.setLookAt({
          position: new Vector3(-0.544, 0.758, 0.341),
          center: new Vector3(-0.543, -0.036, 0.054),
        });
        break;
      //"name": "简阳市", 510185,
      case 510185:
        this.setLookAt({
          position: new Vector3(0.5, 0.932, 0.759),
          center: new Vector3(0.502, -0.147, 0.368),
        });
        break;
      //4个单独的科技区
      case 510199: //成都市本级
        this.setLookAt({
          position: new Vector3(0.5, 0.932, 0.759),
          center: new Vector3(0.7, 0.1, -0.4),
        });
        break;
      case 510140: //高新区
        this.setLookAt({
          position: new Vector3(0.5, 0.1, -0.5),
          center: new Vector3(0.7, 0.1, -0.4),
        });
        break;
      case 510141: //天府新区
        this.setLookAt({
          position: new Vector3(0.48, 0.1, -0.3),
          center: new Vector3(0.7, 0.1, -0.4),
        });
        break;
      case 510142: //东部新区
        this.setLookAt({
          position: new Vector3(0.73, 0.1, -0.3),
          center: new Vector3(0.7, 0.1, -0.4),
        });
        break;
      default:
        break;
    }
  });

  init() {
    super.init();
    this.resetLookAt({
      position: new Vector3(-0.143, 2.051, 0.862),
      center: new Vector3(-0.129, -0.055, 0.11),
    });
    this.controls.enabled = utils.isDev;
  }

  //成都地图
  chengduMap = (() => {
    const chengduMap = new ChengDuMap();
    //three事件
    chengduMap.userData = {
      cursor: 'pointer',
      enableEvent: false,
      glow_enable: false, //启用发光
      glow_color: '#B5E4FF', //发光颜色
      glow_width: 20, //发光厚度(像素)
      glow_opacity: 0.7, //发光透明度(像素)
    };
    this.scene.add(chengduMap);
    return chengduMap;
  })();

  // 发光渲染对象
  glowRenderTerget = new WebGLRenderTarget(128, 128, {
    minFilter: LinearFilter,
    magFilter: LinearFilter,
    format: RGBAFormat,
  });

  // 提取边缘线着色器
  extractEdgeShader = new ShaderMaterial({
    uniforms: {
      map: { value: null }, // 被提取的纹理
      width: { value: 1 }, // 提取的宽度
      color: { value: new Color('#fff') }, // 提取出来的边缘的颜色
      resolution: { value: new Vector2(512, 512) }, // 分辨率
    },
    vertexShader: `
        ${ShaderChunk.common}
        ${ShaderChunk.logdepthbuf_pars_vertex}
        varying vec2 vUv;
        void main() {
            vUv = uv;
            gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
            ${ShaderChunk.logdepthbuf_vertex}
        }
    `,
    fragmentShader: `
        ${ShaderChunk.logdepthbuf_pars_fragment}
        #include <common>
        uniform sampler2D map;
        uniform float width;
        uniform vec3 color;
        uniform vec2 resolution;
        varying vec2 vUv;

        // 二维向量的绕点旋转的方法
        vec2 rotateAround( vec2 p, vec2 center, float angle ) {
            float c = cos( angle );
            float s = sin( angle );
            float x = p.x - center.x;
            float y = p.y - center.y;
            p.x = x * c - y * s + center.x;
            p.y = x * s + y * c + center.y;
            return p;
        }

        void main() {
            float alpha = texture2D(map, vUv).a;
            if(alpha < 0.2){
                discard;                
            }

            float opacity = 1.0;
            
            for(float i = 0.0; i < 2.0; i+= 0.1){
                opacity = min(opacity,  texture2D(map,  rotateAround( (vec2(1.0, 0.0) / resolution * width)+ vUv, vUv , PI * i) ).a);
                if(opacity < 0.2){
                    break;
                }
            }

            if( opacity < 0.2 ){
                gl_FragColor = vec4(color, 1.0);
            }else{
                discard;
                // gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
            }

            // gl_FragColor = texture2D(map, vUv);
            ${ShaderChunk.logdepthbuf_fragment}
        }
    `,
    blending: NoBlending, // 渲染时不与背景融合计算 直接替换
    depthTest: true,
    depthWrite: true,
    transparent: true,
  });

  // 提取离屏渲染对象的边缘
  extractEdge(renderTerget: WebGLRenderTarget, width: number, color: string = '#00ff00') {
    this.copyTextureToRenderTarget(renderTerget.texture, this.renderTarget2, true); // 拷贝并覆盖渲染目标

    const originTarget = this.renderer.getRenderTarget();

    this.clearRendererTargte(renderTerget);
    this.renderer.setRenderTarget(renderTerget);

    fullScreenMesh.material = this.extractEdgeShader;
    this.extractEdgeShader.uniforms.map.value = this.renderTarget2.texture;
    this.extractEdgeShader.uniforms.width.value = width;
    this.extractEdgeShader.uniforms.color.value.set(color);
    fullScreenMesh.render(this.renderer);

    this.renderer.setRenderTarget(originTarget);
  }

  // 渲染描边光效
  renderGlow() {
    this.renderer.clearDepth(); // 清理渲染器的深度
    // const color = {
    //     origin: "#EECD3A",
    //     green: "#5FE2F8"
    // }
    // 渲染整个地图的绿色辉光
    this.object3dToRendererTarget(this.chengduMap, this.glowRenderTerget); // 把地图渲染到离屏渲染对象上面
    this.extractEdge(this.glowRenderTerget, 2, '#B5E4FF'); // 提取地图边缘
    this.renderTargetAddGlow(this.glowRenderTerget, 2, '#B5E4FF'); // 5px 的辉光
    this.renderRendererTarget(this.glowRenderTerget); // 把辉光渲染目标渲染到渲染器上面
  }

  render() {
    super.render();
    const { areaCode } = chengduMap3DStore;
    // if (areaCode === 510100) {
    // this.renderGlow();
    // }
  }
}

const chengduMapRender = (window.chengduMapRender = new ChengduMapRender());

export default chengduMapRender;
